/**
 * 
 */
package sk.stuba.fiit.foo07.genex.gui;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;

import javax.swing.table.DefaultTableModel;

import sk.stuba.fiit.foo07.genex.beans.Question;
import sk.stuba.fiit.foo07.genex.beans.QuestionPoints;
import sk.stuba.fiit.foo07.genex.beans.Test;
import sk.stuba.fiit.foo07.genex.dao.QuestionDao;
import sk.stuba.fiit.foo07.genex.dao.QuestionDaoDerby;
import sk.stuba.fiit.foo07.genex.dao.QuestionTypeDao;
import sk.stuba.fiit.foo07.genex.dao.QuestionTypeDaoDerby;

/**
 * @author _mizu_
 * 
 */
public class NewTestTableModel extends DefaultTableModel {

    /**
     * 
     */
    private static final long serialVersionUID = -3895037570823789366L;

    private int columnCount = 5;
    private String[] columnNames = null;
    private ArrayList<Question> questions;
    private ArrayList<Float> points;
    private QuestionTypeDao qtDao;
    private QuestionDao qDao;

    public NewTestTableModel(Connection c) {
        questions = new ArrayList<Question>();
        points = new ArrayList<Float>();
        qtDao = new QuestionTypeDaoDerby(c);
        qDao = new QuestionDaoDerby(c);
        initColumnNames();
    }

    public NewTestTableModel(Connection c, Test test) throws SQLException {
        qtDao = new QuestionTypeDaoDerby(c);
        qDao = new QuestionDaoDerby(c);
        initColumnNames();

        ArrayList<Question> qList = new ArrayList<Question>();
        ArrayList<Float> pList = new ArrayList<Float>();
        ArrayList<QuestionPoints> qpList = test.getQuestionPoints();

        int i = 0;
        for (QuestionPoints qp : qpList) {
            qList.add(i, qDao.getQuestionByID(qp.getQuestionId()));
            pList.add(i, qp.getPoints());
            i++;
        }

        questions = qList;
        points = pList;

    }

    public void setQuestions(ArrayList<Question> questions,
            ArrayList<Float> points) throws Exception {
        if (points != null && questions.size() != points.size())
            throw new Exception("Length of questions and points must equals!");
        this.questions = questions;
        if (points == null) {
            points = new ArrayList<Float>(questions.size());
            for (Question q : questions)
                this.points.add((float) q.getDifficulty());
        } else
            this.points = points;
        fireTableDataChanged();
    }

    public void addQuestion(Question toAdd, Float points) {
        questions.add(toAdd);
        this.points.add(points);
        fireTableDataChanged();
    }

    public void addQuestions(ArrayList<Question> toAdd, ArrayList<Float> points)
            throws Exception {
        if (questions.size() != points.size())
            throw new Exception("Length of questions and points must equals!");
        questions.addAll(toAdd);
        this.points.addAll(points);
        fireTableDataChanged();
    }

    public void removeQuestions(int[] indices) {
        if (indices.length == 0)
            return;

        for (int i = 0; i < indices.length; i++) {
            questions.remove(indices[i] - i);
            points.remove(indices[i] - i);
        }
        fireTableDataChanged();
    }

    public void setQuestion(Question toSet, int index) {
        questions.set(index, toSet);
        fireTableDataChanged();
    }

    public Question getQuestion(int index) {
        return questions.get(index);
    }

    private void exchange(int index1, int index2) {
        Question temp = questions.get(index1);
        questions.set(index1, questions.get(index2));
        questions.set(index2, temp);
        Float temp2 = points.get(index1);
        points.set(index1, points.get(index2));
        points.set(index2, temp2);
    }

    public void reorder() {
        int[] ind = new int[getQuestionCount()];
        for (int i = 0; i < ind.length; i++)
            ind[i] = i;
        for (int i = 0; i < ind.length - 1; i++) {
            int index = 1 + i + (int) (Math.random() * (ind.length - i - 1));
            exchange(i, index);
        }
        fireTableDataChanged();
    }

    public void moveUp(int index) {
        if (index == 0)
            return;
        exchange(index - 1, index);
        fireTableDataChanged();
    }

    public void moveDown(int index) {
        if (index == questions.size() - 1)
            return;
        exchange(index, index + 1);
        fireTableDataChanged();
    }

    public void initColumnNames() {
        columnNames = new String[columnCount];

        columnNames[0] = new String("#"); // poradove cislo otazky
        columnNames[1] = new String("Otázka");
        columnNames[2] = new String("Typ");
        columnNames[3] = new String("Náročnosť");
        columnNames[4] = new String("Počet bodov");
    }

    @Override
    public int getColumnCount() {
        return columnNames.length;
    }

    @Override
    public int getRowCount() {
        return questions == null ? 0 : questions.size();
    }

    @Override
    public String getColumnName(int col) {
        return columnNames[col];
    }

    @Override
    public void setValueAt(Object val, int row, int col) {
        if (col != 4)
            return;

        try {
            points.set(row, new Float((String) val));
        } catch (NumberFormatException e) {
        }
        fireTableCellUpdated(row, col);
    }

    @Override
    public Object getValueAt(int row, int col) {
        switch (col) {
        // poradove cislo
        case 0:
            return row + 1;

            // text otazky
        case 1:
            return questions.get(row);

            // typ
        case 2:
            //TODO
            //pozor vynimky
            String qt = null;
            try {
                qt = qtDao.getQuestionTypeByQuestionID(
                        questions.get(row).getQuestionID()).getName();
            } catch (Exception e) {
            }
            if ("Single choice".equals(qt))
                return "S";
            else if ("Multi choice".equals(qt))
                return "M";
            else if ("True/False".equals(qt))
                return "TF";
            else if ("Fill in".equals(qt))
                return "F";
            else if ("Essay".equals(qt))
                return "E";
            else
                return "Un";

            // narocnost
        case 3:
            return questions.get(row).getDifficulty();

            // pocet bodov
        case 4:
            return points.get(row);
        }

        return "undefined";
    }

    @Override
    public boolean isCellEditable(int row, int col) {
        if (col == 4)
            return true;

        return false;
    }

    public int getQuestionCount() {
        return questions.size();
    }

    public float getPointsSum() {
        float sum = 0;
        for (Float i : points)
            sum += i;

        return sum;
    }

    public float getAverageDiff() {
        int diffSum = 0;
        for (Question q : questions)
            diffSum += q.getDifficulty();

        return (float) diffSum / questions.size();
    }

    public ArrayList<Question> getQuestions() {
        return questions;
    }

    public ArrayList<Float> getPoints() {
        return points;
    }
}
